home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_08_06
/
8n06060a
< prev
next >
Wrap
Text File
|
1989-11-08
|
14KB
|
571 lines
/*
** dates.cpp -- date object methods
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <dos.h>
#include <string.h>
#include "dates.hpp"
static char ShortMonths[MAXMONTH][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static char LongMonths[MAXMONTH][10] = {
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December"
};
static unsigned MonthDays[MAXMONTH] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static char ShortWeekDays[MAXWEEKDAY+1][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static char LongWeekDays[MAXWEEKDAY+1][10] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
static const char *CurrentDateFormat = "m-dd-yyy";
static int OnHeap = 0; /* CurrentDateFormat doesn't point to heap */
/*
** ChangeDefaultDateFormat -- change the format string used to
** initialize the DateFormatPtr. Return 1 on success or 0 if
** memory could not be allocated for the new string.
*/
int ChangeDefaultDateFormat(const char *s)
{
char *t;
if ((t = strdup(s)) == NULL)
return (0); /* return failure */
if (OnHeap)
free(CurrentDateFormat); /* release old string */
else
OnHeap = 1; /* now we're allocating on heap */
CurrentDateFormat = t; /* point to new string */
return (1);
}
/*
** IsLeap -- return non-zero if Year is a leap year, 0 otherwise.
*/
static int IsLeap(int Year)
{
return (Year % 4 == 0) && (Year % 4000 != 0) &&
((Year % 100 != 0) || (Year % 400 == 0));
}
/*
** DaysInMonth -- return the number of days in Month. Year
** is passed to test for a leap year if the month is February.
*/
static unsigned char DaysInMonth(unsigned char Month, int Year)
{
if ((Month == 2) && IsLeap(Year))
return (29);
else
return (MonthDays[Month - 1]);
}
/*
** CheckForValidDate -- check that Day, Month and Year
** represent a valid date. Return non-zero if so, 0 otherwise.
*/
static int CheckForValidDate(unsigned char Day, unsigned char Month, int Year)
{
if ((Year < MINYEAR) || (Year > MAXYEAR) || (Year == 0) ||
(Month < MINMONTH) || (Month > MAXMONTH))
return (0);
return (Day <= DaysInMonth(Month, Year));
}
/*
** JulianToDayOfWeek -- given a Julian date, return the
** day of the week for that date, 0 being Sunday, 6 being
** Saturday.
*/
static unsigned char JulianToDayOfWeek(long Jul)
{
return ((Jul + 1) % 7);
}
/*
** DMYtoJulian -- after validating the date passed as a Day,
** Month and Year, convert it to a Julian date.
**
** The algorithm shown here is swiped directly from "Numerical
** Recipes in C" by Press, Flannery, Teukolsky and Vettering, p. 10.
*/
#define IGREG (15+31L*(10+12L*1582))
static long DMYtoJulian(unsigned char Day, unsigned char Month, int Year)
{
unsigned long Ja, Jm, Jy, Jul;
if (!CheckForValidDate(Day, Month, Year))
return (BADDATE);
if (Year < 0)
Year++;
if (Month > 2)
{
Jy = Year;
Jm = Month + 1;
}
else
{
Jy = Year - 1;
Jm = Month + 13;
}
Jul = (long) (floor(365.25*Jy) + floor(30.6001*Jm) + Day + 1720995);
if (Day + 31L*(Month + 12L*Year) >= IGREG)
{
Ja = 0.01*Jy;
Jul += 2 - Ja + (int) (0.25*Ja);
}
return (Jul);
}
/* JulianToDMY -- convert a Julian date to the appropriate
** Day, Month and Year.
**
** Also swiped from "Numerical Recipes".
*/
#define GREGOR 2299161
static void JulianToDMY(long Jul, unsigned char *Day, unsigned char *Month,
int *Year)
{
long Ja, JAlpha, Jb, Jc, Jd, Je;
if ((Jul != BADDATE) && (Jul >= MINDATE) && (Jul <= MAXDATE))
{
if (Jul >= GREGOR)
{
JAlpha = ((double) (Jul - 1867216) - 0.25)/36524.25;
Ja = Jul + 1 + JAlpha - (long) (0.25*JAlpha);
}
else
Ja = Jul;
Jb = Ja + 1524;
Jc = 6680.0 + ((double) (Jb - 2439870) - 122.1)/365.25;
Jd = 365*Jc + (0.25*Jc);
Je = (Jb - Jd)/30.6001;
*Day = Jb - Jd - (int) (30.6001*Je);
*Month = Je - 1;
if (*Month > 12)
*Month -= 12;
*Year = Jc - 4715;
if (*Month > 2)
--(*Year);
if (Year <= 0)
--(*Year);
}
}
/*
** ChangeDate -- change a date to reflect the new date passed
** in the arguments. If the requested date is not a legal date,
** return a value of 0 without making any changes. If legal,
** return 1. The date format string is not affected.
*/
int DateObject::ChangeDate(unsigned char NDay, unsigned char NMonth, int NYear)
{
long t;
t = DMYtoJulian(NDay, NMonth, NYear);
if (t != BADDATE)
{
Julian = t;
Day = NDay;
Month = NMonth;
Year = NYear;
DayOfWeek = JulianToDayOfWeek(Julian);
return (1);
}
return (0);
}
/*
** DateObject -- constructor if no args given. Just initialize
** to todays date.
*/
DateObject::DateObject(void)
{
union REGS regs;
regs.x.ax = 0x2a00; /* DOS get date service */
intdos(®s, ®s);
Day = regs.h.dl;
Month = regs.h.dh;
Year = regs.x.cx;
DayOfWeek = regs.h.al;
Julian = DMYtoJulian(Day, Month, Year);
DateFormatPtr = strdup(CurrentDateFormat);
if (DateFormatPtr == NULL)
Julian = BADDATE;
}
/*
** DateObject -- copy initializer constructor
*/
DateObject::DateObject(DateObject &OtherDate)
{
Day = OtherDate.Day;
Month = OtherDate.Month;
Year = OtherDate.Year;
DayOfWeek = OtherDate.DayOfWeek;
Julian = OtherDate.Julian;
DateFormatPtr = strdup(OtherDate.DateFormatPtr);
if (DateFormatPtr == NULL)
Julian = BADDATE;
}
/*
** DateObject -- constructor when day, month and year initializers
** are provided. The default format string is used.
*/
DateObject::DateObject(unsigned char InitDay, unsigned char InitMonth,
int InitYear)
{
ChangeDate(InitDay, InitMonth, InitYear);
if (Julian != BADDATE)
{
DateFormatPtr = strdup(CurrentDateFormat);
if (DateFormatPtr == NULL)
Julian = BADDATE;
}
}
/*
** DateObject -- constructor used when day, month, year and a
** format string initializer are provided.
*/
DateObject::DateObject(unsigned char InitDay, unsigned char InitMonth,
int InitYear, const char *FormatStr)
{
ChangeDate(InitDay, InitMonth, InitYear);
if (Julian != BADDATE)
{
DateFormatPtr = strdup(FormatStr);
if (DateFormatPtr == NULL)
Julian = BADDATE;
}
}
/*
** = -- assignment operator.
*/
DateObject DateObject::operator = (DateObject &d)
{
Day = d.Day;
Month = d.Month;
Year = d.Year;
Julian = d.Julian;
DayOfWeek = d.DayOfWeek;
DateFormatPtr = strdup(d.DateFormatPtr);
if (DateFormatPtr == NULL)
Julian = BADDATE;
return (*this);
}
/*
** + -- addition operator. This is the fundamental operator
** function. All other arithmetic operators returning
** DateObjects call this function. The resulting DateObject
** copies that format string of the DateObject argument.
*/
DateObject operator + (DateObject &d, long x)
{
DateObject sum;
sum.Julian = d.Julian + x;
if ((sum.Julian < MINDATE) || (sum.Julian > MAXDATE))
sum.Julian = BADDATE;
else
{
JulianToDMY(sum.Julian, &(sum.Day), &(sum.Month), &(sum.Year));
sum.DayOfWeek = JulianToDayOfWeek(sum.Julian);
sum.DateFormatPtr = strdup(d.DateFormatPtr);
if (sum.DateFormatPtr == NULL)
sum.Julian = BADDATE;
}
return (sum);
}
DateObject operator + (long x, DateObject &d)
{
return (d + x);
}
DateObject DateObject::operator - (long x)
{
return (*this + (-x));
}
DateObject DateObject::operator ++ (void)
{
return ((*this) = (*this) + 1L);
}
DateObject DateObject::operator -- (void)
{
return ((*this) = (*this) + (-1L));
}
DateObject DateObject::operator += (long x)
{
return ((*this) = (*this) + x);
}
DateObject DateObjec